package com.xxmw.transaction.common.utils.bourse;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xxmw.transaction.common.excep.service.TransactionException;
import com.xxmw.transaction.common.utils.Assert;
import com.xxmw.transaction.common.utils.Constant;
import com.xxmw.transaction.common.utils.HmacUtil;
import com.xxmw.transaction.common.utils.http.HttpClientUtil;
import com.xxmw.transaction.common.utils.http.HttpHeader;
import com.xxmw.transaction.common.utils.symbolFormat.SymbolFormat;
import com.xxmw.transaction.enumeration.BourseEnum;
import com.xxmw.transaction.enumeration.TradeTypeEnum;
import com.xxmw.transaction.model.app.BourseApi;
import com.xxmw.transaction.model.app.BourseOrder;
import com.xxmw.transaction.model.robot.RobotOrder;
import com.xxmw.transaction.vo.BalanceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 久币交易所工具类
 * https://www.99ex.com/docs/zh/
 * @author luowenliang
 * @since 2020/5/12 16:21
 */
@Slf4j
public class JiuBiUtil {

    private static final String DOMAIN = "https://www.99ex.cc";

    /**
     * 下单请求路径
     */
    private static final String ORDER_PATH = "/api/spot/v3/orders";

    /**
     * 订单信息
     * GET/api/spot/v3/orders/<client_oid>
     * 或GET/api/spot/v3/orders/<order_id>
     */
    private static final String ORDER_INFO_PATH = "/api/spot/v3/orders/";

    /**
     * 获取币种账户信息
     */
    private static final String ACCOUNT_CURRENCY_PATH = "/api/account/v3/wallet/";

    private static final SymbolFormat symbolFormat = BourseEnum.OKEX.getSymbolFormat();

    /**
     * 下单
     * @param api
     * @param order
     */
    public static void order (BourseApi api, BourseOrder order) {

        String jsonParam = OkexUtil.getOrderBody(order).toJSONString();
        String timeStamp = OkexUtil.getTimestamp();

        StringBuilder sb = new StringBuilder();
        sb.append(timeStamp).append(Constant.RequestType.POST.name()).append(ORDER_PATH).append(jsonParam);

        log.info("久币待签名字符串：{}", sb.toString());

        String sign = HmacUtil.huobiSign(sb.toString(), api.getSecretKey());

        HttpHeader header = new HttpHeader();
        header.add("OK-ACCESS-KEY", api.getAccessKey());

        //对timestamp + method + requestPath + body字符串(+表示字符串连接)使用HMAC SHA256方法加密，通过BASE64编码输出而得到的
        //method是请求方法，字母全部大写。
        //requestPath是请求接口路径。
        //body是指请求主体的字符串，如果请求没有主体(通常为GET请求)则body可省略
        header.add("OK-ACCESS-SIGN", sign);
        header.add("OK-ACCESS-PASSPHRASE", api.getPassphrase());
        header.add("OK-ACCESS-TIMESTAMP", timeStamp);
        String res = HttpClientUtil.post(DOMAIN + ORDER_PATH, header, jsonParam);
        log.info("久币下单接口返回：{}", res);
        JSONObject jsonObject = JSONObject.parseObject(res);
        if (jsonObject != null && jsonObject.getBoolean("result") != null) {
            if (jsonObject.getBoolean("result")) {
                order.setStatus(BourseOrder.Status.PUBLISHED.value());
                order.setOutId(jsonObject.getString("order_id"));
            } else {
                order.setStatus(BourseOrder.Status.PUBLISH_ERROR.value());
                order.setRemark(jsonObject.getString("error_message"));
                log.error("久币订单" + order.getId() + "下单失败:{}", res);
            }
        } else {
            order.setStatus(BourseOrder.Status.PUBLISH_ERROR.value());
            log.error("久币下单接口返回信息为空");
        }
    }

    /**
     * 订单信息
     * @param api
     * @param order
     */
    public static void orderInfo (BourseApi api, BourseOrder order) {
        StringBuilder body = new StringBuilder();
        //获取当前时间 对应ok 时间戳
        String timestamp = OkexUtil.getTimestamp();
        body.append(timestamp).append(Constant.RequestType.GET.name()).append(ORDER_INFO_PATH + order.getOutId() + "?instrument_id=" + symbolFormat.symbolFormat(order.getBaseCurrency(),order.getQuoteCurrency()));
        //获取签名
        String sign = HmacUtil.huobiSign(body.toString(), api.getSecretKey());

        HttpHeader header = new HttpHeader();
        header.add("OK-ACCESS-KEY", api.getAccessKey());
        header.add("OK-ACCESS-SIGN", sign);
        header.add("OK-ACCESS-TIMESTAMP", timestamp);
        header.add("OK-ACCESS-PASSPHRASE", api.getPassphrase());
        //获取订单详情
        String res = HttpClientUtil.get(DOMAIN + ORDER_INFO_PATH + order.getOutId() + "?instrument_id=" + symbolFormat.symbolFormat(order.getBaseCurrency(), order.getQuoteCurrency()), header);
        log.info("久币查询订单详情的结果为：{}",res);
        //返回结果处理
        JSONObject jsonObject = JSONObject.parseObject(res);
        if (jsonObject != null) {
            String status = jsonObject.getString("state");
            String avg = jsonObject.getString("price_avg");
            order.setStatus(OkexUtil.getOrderStatus(status));
            if (!StringUtils.isEmpty(avg)){
                order.setAvgPrice(new BigDecimal(avg));
                order.setDealNum(jsonObject.getBigDecimal("filled_size"));
            }
        } else {
            log.error("久币订单查询无响应");
        }
    }


    /**
     * 获取账户币种月信息
     * @param api
     * @param currency
     * @return
     */
    public static BalanceVo getBalance (BourseApi api, String currency) {
        BalanceVo balanceVo =  balanceObject(api, currency);
        return balanceVo;
    }

    public static Map<String, BalanceVo> getBalance (BourseApi api, List<String> currency) {
        Map<String, BalanceVo> map = new HashMap<>(16);
        if (currency.size() <= 0) {
            return map;
        }
        for (String s : currency) {
            map.put(s, getBalance(api, s));
        }
        return map;
    }

    public static BalanceVo balanceObject (BourseApi api, String currency) {

        StringBuilder body = new StringBuilder();

        String url = DOMAIN + ACCOUNT_CURRENCY_PATH + currency.toUpperCase();
        //获取当前时间 对应ok 时间戳
        String dateTime = OkexUtil.getTimestamp();
        body.append(dateTime).append(Constant.RequestType.GET.name()).append(ACCOUNT_CURRENCY_PATH + currency.toUpperCase());
        //获取签名
        String sign = HmacUtil.huobiSign(body.toString(), api.getSecretKey());
        log.info("签名前信息：{}", body.toString());
        log.info("时间：{}", dateTime);
        log.info("签名后数据为：{}", sign);
        HttpHeader headers = new HttpHeader();
        headers.add("OK-ACCESS-KEY", api.getAccessKey());
        headers.add("OK-ACCESS-SIGN", sign);
        headers.add("OK-ACCESS-TIMESTAMP", dateTime);
        headers.add("OK-ACCESS-PASSPHRASE", api.getPassphrase());

        String res = HttpClientUtil.get(url, headers);
        log.info("久币返回信息为：{}", res);
        BalanceVo balanceVo = new BalanceVo();
        try {
            JSONArray array = JSONArray.parseArray(res);
            if (array.size() > 0) {
                JSONObject object = array.getJSONObject(0);
                if (Assert.isNotNullOrEmpty(object.getBigDecimal("available"))) {
                    balanceVo.setAvailable(object.getBigDecimal("available"));
                }
                if (Assert.isNotNullOrEmpty(object.getBigDecimal("hold"))) {
                    balanceVo.setFrozen(object.getBigDecimal("hold"));
                }
                if (Assert.isNotNullOrEmpty(object.getBigDecimal("balance"))) {
                    balanceVo.setTotal(object.getBigDecimal("balance"));
                }
            }
        } catch (Exception e) {
            throw new TransactionException("久币获取账户余额异常");
        }
        return balanceVo;
    }

    public static void main(String[] args) {
        BourseApi api = new BourseApi();
        api.setAccessKey("f3293724-9f4c-4d22-9d87-0a4bb0f6f8aa");
        api.setSecretKey("89D6CAAC365B4CDBF05B75C90BBF1DC8");
        api.setPassphrase("yamoo1206");

        BourseOrder order = new BourseOrder();
        order.setTradeType(TradeTypeEnum.BUY_MARKET.getValue());
        order.setSymbol("ethusdt");
        order.setQuoteCurrency("usdt");
        order.setBaseCurrency("eth");
        order.setNum(BigDecimal.ONE);
        order.setPrice(new BigDecimal("129"));
        order.setId(123431L);
        order(api, order);
//        BalanceVo btc = balanceObject(api, "btc");
//        log.info(btc.toString());

    }


    /*public static void main(String[] args) {
        BourseApi api = new BourseApi();
        api.setAccessKey("d069f8d5-6373-4896-80d1-697231f707af");
        api.setSecretKey("A6EDF2B272C0B0335228B35D243FD35C");
        api.setPassphrase("luowenliang");

        RobotOrder robotOrder = new RobotOrder();
        robotOrder.setId(1L);
        robotOrder.setOutId("13231");
        robotOrder.setSymbol("ethusdt");
        robotOrder.setTradeType(TradeTypeEnum.BUY_LIMIT.getValue());
        robotOrder.setNum(new BigDecimal("1"));
        robotOrder.setPrice(new BigDecimal("12"));
        robotOrder.setBaseCurrency("eth");
        robotOrder.setQuoteCurrency("usdt");

        order(api, robotOrder);
    }*/
}
